<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../../assets/css/base.css">
</head>
<body>
    <!-- <input type="button" value="按钮" id="aaa" onclick="show(event)">
    <script>
        function show(){}
        let btnDom = document.querySelector("#aaa");
        btnDom.addEventListener("click",function(){
            console.log("点击")
        })
        btnDom.addEventListener("aaaa",function(){
            console.log("自定义事件")
        })
    </script>
    <hr> -->
    <div id="app">
        <pre v-pre class="note">
        1、组件的嵌套的页面，在父组件渲染时需要对子组件也进行实例的创建,所以子组件的创建时间永远时晚于父组件的;
        2、因为子组件的创建时间永远时晚于父组件，所以子组件的仓库【数据、方法……】创建永远晚于父组件;
        3、因为子组件数据的构建时间晚于父组件的页面渲染，所以需要选择一个可以提前完成定义，并在需要的时候进行执行的代码实现数据传递；
        4、所以能够同时满足上述两个条件的JS技术只有方法功能；【 方法定义(形参) + 方法调用(实参) 】
        5、方法定义的形参在代码是用于接收数据的，所以在父组件定义;方法调用的实参是提供数据的，所以在子组件中进行调用；

        子向父数据传递实现方案:事件绑定+事件触发
            + 事件绑定:在子组件标签上以 v-on 语法为子组件标签绑定自定义事件，指向父组件的方法仓库方法;
            + 事件触发(事件拦截触发):在子组件标签上绑定的自定义事件，在子组件解析渲染时会被自动记录在子组件的$attrs实例属性中；
                                   绑定的事件名会被转为以 on开头的驼峰事件名 =例如=> v-on:state -> $attrs:{ onState:function($event){} };
                                   在$attrs中被加载的自定义事件，可以通过属性emits进行拦截，被拦截的事件将从$attrs中移除；
                                   被emits拦截的事件，通过vue实例的内置实例方法 $emit 进行触发 => $emit("emits拦截的事件名",传递的事件源参数);
                                   + $emits 的第一个作用是为了在代码上 区分 方法调用和事件触发
                                   + $emits 可以在调试工具中记录传递的日志【单向数据流】
        </pre>
        <input type="button" value="点击事件" v-on:click="printEvent($event)">
        <h5>父组件</h5>
        <p>子组件msg:{{ msg }}</p>
        <p>子组件arr:{{ arr }}</p>
        <!-- 
            v-on:msg 是为子组件提供自定义事件;
            子组件就可以触发自定义事件 onMsg;
            onMsg的事件回调 是 父组件方法 getMsg; 
        -->
        <my-comp v-on:msg=" getMsg($event) " @arr=" getArr "></my-comp>
    </div>

    <script type="text/x-template" id="myComp">
        <div class="cbox">
            <h5>子组件</h5>
            <p>msg:{{ msg }}</p>
            <input type="button" value="执行绑定的MSG事件" @click="emitMsgEvent()">
            <p>arr:{{ arr }}</p>
            <input type="button" value="执行绑定的ARR事件" @click="emitArrEvent()">

        </div>
    </script>

    <script type="module">
        import { createApp } from "../../assets/vue3/vue.esm-browser.js";

        const MyComp = {
            template:"#myComp",
            emits:["arr"],
            data() {
                return {
                    msg:"子组件的数据",
                    arr:[1,2,3,4,5]
                }
            },
            methods: {
                emitMsgEvent() {
                    let event = {
                        type:"自定义事件onMsg",
                        msg:this.msg
                    }
                    this.$attrs.onMsg(event)
                },
                emitArrEvent(){
                    this.$emit("arr",this.arr)
                }
            },
            created () {
                console.log("子组件created-仓库创建完成")
            },
        }

        createApp({
            components: {
                MyComp,
            },
            data() {
                return {
                    msg:"",
                    arr:[]
                }
            },
            methods: {
                printEvent(e) {
                    console.log("点击的事件源对象:",e)
                },
                getMsg(e){
                    console.log("父组件方法getMsg:",e)
                    this.msg = e.msg;
                },
                getArr(e){
                    this.arr = e;
                }
            },
            created () {
                console.log("父组件created-仓库创建完成")
            },
        }).mount("#app")
    </script>
</body>
</html>